use crate::exchange::bitget::BITGET_RULE;
use crate::exchange::lib::{BINANCE_RULE, CONFIG, Exchange};
use crate::public::Rule;
use crate::utils::TimeDomain;
use chrono::Utc;
use std::collections::HashSet;
use std::str::FromStr;
use std::sync::Arc;
use std::time::Duration;

mod exchange;
mod public;
mod utils;

async fn get_rule(exchange: &str) -> HashSet<String> {
    let exchange = Exchange::from_str(exchange).unwrap();

    match exchange {
        Exchange::Bitget => {
            BITGET_RULE
                .get_or_init(async || {
                    let a = exchange::bitget::rest::Rest;
                    a.get_rule().await
                })
                .await;

            BITGET_RULE.get().unwrap().clone()
        }
        Exchange::Ourbit => {
            let a = exchange::ourbit::rest::Rest;
            a.get_rule().await
        }
        Exchange::Lbank => {
            let a = exchange::lbank::rest::Rest;
            a.get_rule().await
        }

        Exchange::Xt => {
            let a = exchange::xt::rest::Rest;
            a.get_rule().await
        }

        Exchange::Btse => {
            let a = exchange::btse::rest::Rest;
            a.get_rule().await
        }
    }
}

fn set_intersection(a: &HashSet<String>, b: &HashSet<String>) -> Vec<String> {
    let mut a: Vec<String> = a.intersection(&b).cloned().collect();
    a.sort();

    a
}

fn split_array(public_symbol: &[String]) -> Vec<String> {
    let a = public_symbol.chunks(CONFIG.split as usize);

    for (index, i) in a.enumerate() {
        if index != CONFIG.node as usize {
            continue;
        }

        return i.to_vec();
    }

    unreachable!()
}

#[tokio::main]
async fn main() {
    rustls::crypto::ring::default_provider()
        .install_default()
        .unwrap();

    BINANCE_RULE
        .get_or_init(async || {
            let a = exchange::binance::rest::Rest;
            a.get_rule().await
        })
        .await;

    // 获取副所交易对
    let coin_exchange = get_rule(CONFIG.exchange.as_str()).await;

    // 主所, 副所进行交集
    let public_symbol = set_intersection(&BINANCE_RULE.get().unwrap(), &coin_exchange);

    println!("交易对: {}", public_symbol.len());

    // 切割数组, 返回此次要订阅的交易对
    let sub_symbol = Arc::new(split_array(&public_symbol));

    let symbol_clone_1 = sub_symbol.clone();
    let symbol_clone_2 = sub_symbol.clone();

    // 订阅币安
    tokio::spawn(async move {
        exchange::binance::ws::ws(symbol_clone_1.clone()).await;
    });

    // 订阅副所
    let handler = match Exchange::try_from(CONFIG.exchange.as_str()).unwrap() {
        Exchange::Bitget => tokio::spawn(async move {
            exchange::bitget::ws::ws(symbol_clone_2).await;
        }),
        Exchange::Ourbit => tokio::spawn(async move {
            exchange::ourbit::ws::ws(symbol_clone_2).await;
        }),
        Exchange::Lbank => tokio::spawn(async move {
            exchange::lbank::ws::ws(symbol_clone_2).await;
        }),
        Exchange::Xt => tokio::spawn(async move {
            exchange::xt::ws::ws(symbol_clone_2).await;
        }),

        Exchange::Btse => tokio::spawn(async move {
            exchange::btse::ws::ws(symbol_clone_2).await;
        }),
    };

    // 定时创建新的日志目录
    tokio::spawn(async {
        tokio::fs::create_dir_all(format!("./data/{}", TimeDomain::get_date()))
            .await
            .unwrap();

        loop {
            let tomorrow_utc = Utc::now() + chrono::Duration::days(1);

            // 格式化为YYYY-MM-DD字符串
            let formatted_date = tomorrow_utc.format("%Y-%m-%d").to_string();

            tokio::fs::create_dir_all(format!("{}{formatted_date}", CONFIG.write_path))
                .await
                .unwrap();

            tokio::time::sleep(Duration::from_secs(3600)).await;
        }
    });

    handler.await.unwrap();
}
